-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
scatter marker color gradients #1620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- radial, horizontal, and vertical - for all svg scatter types
src/components/drawing/index.js
Outdated
// scaled by given max and min to colorscales | ||
var markerScale = drawing.tryColorscale(marker, ''), | ||
lineScale = drawing.tryColorscale(marker, 'line'); | ||
drawing.gradient = function(sel, gd, type, color1, color2) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was debating whether this goes in color
or drawing
- ended up deciding on drawing
primarily because it's tied to gd
(so it can create defs
in the right place, without having to walk the tree with Lib.getPlotDiv
for every marker) and nothing else in color
is... but could be persuaded otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This belongs in Drawing
no doubt. Color
is really a lib (i.e. utility) module that shouldn't know anything about plotly attributes and especially gd
.
@@ -107,7 +107,8 @@ module.exports = { | |||
line: extendFlat({}, | |||
{width: scatterMarkerLineAttrs.width}, | |||
colorAttributes('marker'.line) | |||
) | |||
), | |||
gradient: scatterMarkerAttrs.gradient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: test image with carpet plots. Somehow imagetest
isn't working for me yet with carpets, must be something I still need to update?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rm -rf node_modules
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another TODO: looks like this PR broke gl2d
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify which PR? Do you mean scattercarpet or this PR? Edit: realizing you probably mean these attributes need to be either added+implemented or properly avoided in gl2d.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scattercarpet image test in 105ce9b
gl2d fix still to come.
@@ -31,7 +38,14 @@ | |||
], | |||
"subplot": "ternary2", | |||
"name": "b missing", | |||
"uid": "6c0753" | |||
"uid": "6c0753", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might as well 🔪 those uid
fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔪 🔪 🔪 a074259
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -15,12 +15,18 @@ var colorscaleDefaults = require('../../components/colorscale/defaults'); | |||
|
|||
var subTypes = require('./subtypes'); | |||
|
|||
|
|||
/* | |||
* opts: object of flags to control features not all marker users support |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for 🔒 ing this pattern. 🎉
* except all at once before a full redraw. | ||
* The upside of this is arbitrary points can share gradient defs | ||
*/ | ||
drawing.initGradients = function(gd) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice pattern. Controlling gradient defs
in one place should help us in #581 too.
@@ -153,6 +153,9 @@ Plotly.plot = function(gd, data, layout, config) { | |||
makePlotFramework(gd); | |||
} | |||
|
|||
// clear gradient defs on each .plot call, because we know we'll loop through all traces | |||
Drawing.initGradients(gd); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to add jasmine test checking that restyle
can update gradient defs
properly.
src/components/drawing/index.js
Outdated
).replace(/[^\w\-]+/g, '_'); | ||
var gradient = fullLayout._defs.select('.gradients').selectAll('#' + gradientID).data([0]); | ||
|
||
gradient.enter() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect this algo would work for adding gradients to bar traces? Would be a cool feature 😏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, would be cool to add bar gradients... for another PR
test/jasmine/tests/drawing_test.js
Outdated
['radial', '#456', '#fff'], | ||
['radial', '#456', '#eee'], | ||
['radial', '#456', '#ddd'] | ||
]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not happy with this... there are a bunch of ways for it to blow up in actual use, like if someone makes 1000 different gradients via different marker colors, and animates them through 1000 intermediate states, suddenly you have a million gradients lying around.
I think I need to change it to associating the gradient with the point rather than with the color combo - unless someone has another idea how to keep this in check.
src/components/drawing/index.js
Outdated
else gradientColor = markerGradient.color; | ||
|
||
var gradientID = 'g' + gd._fullLayout._uid + '-' + trace.uid; | ||
if(perPointGradient) gradientID += '-' + i; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now we're making either one gradient for the whole trace (if we can) or one per point (if any of the attributes varies per point) and it will update if the attributes change. This means that several traces (or several points in one trace with array attributes) will no longer be able to share a gradient def, but I don't think there are any cases where this can blow up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds right 👍
@@ -15,6 +15,9 @@ var Lib = require('../../lib'); | |||
// arrayOk attributes, merge them into calcdata array | |||
module.exports = function arraysToCalcdata(cd, trace) { | |||
|
|||
// so each point knows which index it originally came from | |||
for(var i = 0; i < cd.length; i++) cd[i].i = i; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@etpinard to my comment earlier today about not using calcdata
as much: I needed to put this in because what I first tried to do, getting the index from the selection .each(d, i)
, is not reliable, as evidenced by the scattercarpet test image: the 0th point on the plot was actually index 1 from the trace (point 0 is cut off), but then the legend thought IT was point 0 so overwrote the other point 0 gradient.
BUT once we have that, we could get rid of the rest of these Lib.mergeArray
statements - which, to address your concern earlier, don't do any sanitization anyway, we only do that for the axis data - and just directly access the arrays (if they are arrays) from within the style routines.
I'm not going to do that now, but could be a nice 🚀 at some point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good 👁️ here and nice fix. But, I think the solution would be to make Lib.mergeArray
sanatize those arrays instead of 🔪 it. We can debate this in a future issue / PR 😄
lineScale = drawing.tryColorscale(marker, 'line'); | ||
var markerScale = drawing.tryColorscale(marker, ''); | ||
var lineScale = drawing.tryColorscale(marker, 'line'); | ||
var gd = Lib.getPlotDiv(s.node()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it might be better to add a ref to those gradient defs in fullData[i]
then to look for gd
? Or even better refactor those Drawing
method to expect fullLayout
as argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll leave it for now - I agree this is suboptimal but neither of these alternatives seems particularly simpler to me. If I had to pick one I'd probably go for the first actually... stashing the <defs>
in each trace could come in handy elsewhere too.
I'm not a big fan of that 💃 nicely done. |
cc @etpinard @charleyferrari - I won't be able to make changes until I'm back online mid-late week but wanted to post this for review.